/*
 * CLitePlayer.h
 *
 *  Created on: 2016年3月17日
 *      Author: terry
 */

#ifndef CLITEPLAYER_H_
#define CLITEPLAYER_H_

#include "LitePlayer.h"
#include "MediaObject.h"
#include "CommandThread.h"
#include "ParamSet.h"
#include <map>
#include "MediaSourceFactory.h"
#include "FileMediaSink.h"
#include "FrameFilter.h"
#include "InputMediaSource.h"
#include "AVFramePtrQueue.h"
#include "TimeChecker.h"


namespace av
{


class CLitePlayer: public InputPlayer, public util::CommandThread, public MediaDecoderSink, public RenderEventSink
{
public:
	CLitePlayer();
	virtual ~CLitePlayer();

	/**
	 * 打开媒体流
	 * @param url 		媒体源URL
	 * @return 0 表示成功
	 */
	virtual int open(const char* url, const char* params);

	/**
	 * 关闭媒体流
	 */
	virtual void close();

	/**
	 * 媒体流是否打开
	 * @return true 表示媒体流已经打开就绪
	 */
	virtual bool isOpen();

	/**
	 * 获取媒体URL
	 * @return URL
	 */
	virtual const char* getURL();

	/**
	 * 获取媒体流格式
	 * @param fmt
	 * @return true 表示成功
	 */
	virtual bool getFormat(MediaFormat& fmt);

	/**
	 * 获取媒体流时长，单位为毫秒
	 * @return 媒体流时长，如果是实时流，返回0
	 */
	virtual int getDuration();

	/**
	 * 播放
	 * return 0 表示成功
	 */
	virtual int play();

	virtual int pause();

	virtual void stop();

	/**
	 * 获取播放状态
	 * @return 播放状态，@see StreamState
	 */
	virtual int getState();


	/**
	 * 判断是否可定位
	 * @return true 表示可定位
	 */
	virtual bool seekable();


	/**
	 * 定位到指定时间点
	 * @param offset    时间点，单位为毫秒，不应超过 duration
	 * @return 0 表示成功
	 */
	virtual int seek(int64_t offset);

	/**
	 * 获取当前已播放时长
	 * @return 播放时间，单位为毫秒
	 */
	virtual int64_t getTime();


	/**
	 * 设置播放速度，正常播放速度为 1.0
	 * @param scale 播放速度，取值范围: [1/8, 8]
	 * @return 0 表示成功
	 */
	virtual int setScale(float scale);

	/**
	 * 获取播放速度
	 * @return 播放速度
	 */
	virtual float getScale();

	virtual int step();

	virtual int nextKeyFrame();

	/**
	 * get current volume
	 * @return [0.0, 1.0]
	 */
	virtual float getVolume();

	/**
	 * 设置音量
	 * @param vol 音量，取值范围为：[0, 1.0]
	 * @return
	 */
	virtual int setVolume(float vol);

	virtual bool isMute();

	/**
	 * 设置静音
	 * @param muted true表示静音， false表示打开声音
	 * @return 0 表示成功
	 */
	virtual int setMute(bool muted);

	virtual bool isFullscreen();

	/**
	 * 设置全屏
	 * @param full 表示全屏
	 * @return 0 表示成功
	 */
	virtual int setFullscreen(bool full);

	/**
	 * 设置视频显示窗口
	 * @param hwnd
	 * @return
	 */
	virtual void setVideoWnd(void* hwnd);

	virtual void setVideoWindow(VideoWindow* window);

	/**
	 * 设置视频宽高比率
	 * 如果width,height = 0, 保持视频的原始比率
	 * @param width
	 * @param height
	 * @return 0 on success
	 */
	virtual int setRatio(int width, int height);

	virtual void getRatio(int& width, int& height);

	/**
	 * 设置播放器logo
	 * @param filepath
	 * @return
	 */
	virtual int setImage(const char* filepath);


	/**
	 * 抓图
	 * @param filepath 图片路径
	 * @return 0 表示成功
	 */
	virtual int snap(const char* filepath);


	/**
	 * 设置过滤器, 参考avfilter设置
	 * @param filterString
	 * @return 0 表示成功
	 */
	virtual int setVideoFilter(const char* filterString);


	virtual int addOverlay(int idx, Overlay& osd);

	virtual int removeOverlay(int idx);

	virtual void clearOverlay();

	virtual void setOverlay(const Overlay* osds, size_t size);

	/**
	* 设置解码回调
	* @param pSink 接收解码后的媒体帧
	*/
	virtual void setFrameSink(MediaFrameSink* pSink);

	/**
	 * 设置媒体流回调
	 * @param pSink 接收未解码媒体包
	 */
	virtual void setPacketSink(MediaPacketSink* pSink);


	virtual void setEventSink(MediaEventSink* pSink);




	virtual int togglePlay();

	virtual int toggleMute();

	virtual int toggleFull();

	/**
	 * 减速播放
	 * @return
	 */
	virtual int slow();

	/**
	 * 快速播放
	 * @return
	 */
	virtual int fast();


	virtual int startRecord(const char* filename);

	/**
	 * 停止录像
	 */
	virtual void stopRecord();

	/**
	 *  是否在录像中
	 */
	virtual bool isRecording();

	virtual bool getMetaData(const std::string& key, std::string& value);


    virtual int open(const MFormat& fmt);

    virtual bool write(MPacket& pkt);

    virtual void writeEnd();

    virtual void flush();

	virtual void setDelayTime(int ms);


    /**
     * 获取属性
     * @param name 属性名
     * @return 属性值
     */
    virtual size_t getProp(const char* name, char* value, size_t size);

    /**
     * 设置属性
     * @param name 属性名称
     * @param value 属性值
     * @return true 表示成功
     */
    virtual bool setProp(const char* name, const char* value);

    virtual bool existProp(const char* name);


    /**
     * 运行/禁止鼠标绘制图形
     * @param enabled
     */
    virtual void enableDrawGraph(int mode);

    /**
     * 设置绘制图形, JSON 格式
     * @param value	JSON字符串, 为NULL或者空表示清理图形
     * @param size
     */
    virtual void setDrawGraph(const char* value, size_t size);

    /**
     * 获取绘制图形, JSON 格式
     * @return
     */
    virtual const char* getDrawGraph();



    void setSourceFactory(MediaSourceFactoryPtr& factory);

    MediaSourcePtr createSource(const std::string& url, const std::string& params);

protected:
	virtual void onCommand(Command& cmd);
	virtual void onIdle();
	virtual bool startup();
	virtual void cleanup();
    virtual void doStop();


	virtual void onDecodeFrame(AVFramePtr frame);

	virtual void onRenderEvent(const RenderEvent& event);

protected:
	enum PlayerCommandType
	{
		kOpen = 1,
		kClose,
		kPlay,
		kPause,
		kStop,
		kSeek,
		kFlush,

		kSetScale,
		kStep,
		kNextKeyFrame,

		kSetVideoWnd,

		kSetVideoFilter,
		kSetProp,

		kSnap,
		kStartRecord,
		kStopRecord,

		kSetDelayTime
	};

protected:

	void handleOpen();
	void handleClose();
	void handlePlay();
	void handlePause();
	void handleStop();
	void handleSeek(int64_t offset);
	void handleSetScale(AVRational scale);
	void handleStep();
	void handleNextKeyFrame();
	void handleSetVideoWnd(void* hwnd);
	void handleSnap(const std::string& filePath);
	void handleFlush();
	void handleStartRecord(const std::string& filePath);
	void handleStopRecord();

	void handleSetVideoFilter(const std::string& str);
	void handleSetProp(std::string& key, std::string& value);

	void handleSetDelayTime(std::string& value);
	void handleAudioChanged(std::string& value);

	void fireMediaEvent(int type, int64_t value);
	void fireMediaPacket(AVPacketPtr& pkt);
	void fireMediaFrame(AVFramePtr& frame);
	void fireMediaFormat(const MediaFormat& fmt);


	void doCloseFile();

	void setState(StreamState state);

	void setupFilter();
	void cleanupFilter();

	void filterVideoFrame(AVFramePtr& frame);

	void dispatchPacket(AVPacketPtr& pkt);
	int computeDelay(AVPacketPtr& pkt);

	bool readUntilVideoFrame();

	bool readUntilVideoKeyFrame();

	int64_t getClock();

	void handleOpenSource();

	void handleAudioChanged(MediaCodec codec, int channels, int samplerate);

    void resetTimePoint();

protected:
	std::string 	m_url;
	util::ParamSet	m_params;

	MediaFormat		m_format;
	MFormat m_fmt;
	bool	m_formatReady;

	StreamState		m_state;
	AVRational	    m_scale;

	comn::CriticalSection	m_cs;

	MediaSourcePtr  m_source;
	std::shared_ptr< InputMediaSource > m_inputSource;

	VideoDecoderPtr	m_videoDecoder;
	AudioDecoderPtr	m_audioDecoder;
	VideoRenderPtr	m_videoRender;
	AudioRenderPtr  m_audioRender;

	MediaPacketSink*	m_packetSink;
	MediaFrameSink*		m_frameSink;
	MediaEventSink*		m_eventSink;

	MediaSourceFactoryPtr	m_sourceFactory;

	FileMediaSinkPtr	m_fileSink;


	std::shared_ptr< VideoFrameFilter >	m_videoFilter;
	std::string	m_vfilterString;

	bool	m_isLive;
	TimePoint	m_lastPoint[2];

	bool	m_waitForKeyFrame;	/// 等待视频关键帧 
    int64_t m_videoFrameCount;
    int64_t	m_curTime;

	std::string	m_snapFilePath;

	AVFramePtrQueue	m_frameQueue;
	int	m_delayTime;
	int64_t	m_subtitlePts;

	util::TimeChecker	m_ptsChecker;

};



} /* namespace av */

#endif /* CLITEPLAYER_H_ */
